package vip.liux.backend.infrastructure.excel;

import com.alibaba.excel.EasyExcelFactory;
import org.apache.commons.lang3.reflect.ConstructorUtils;
import vip.liux.backend.infrastructure.excel.converters.DateStringConverter;
import vip.liux.backend.infrastructure.excel.converters.LocalDateStringConverter;
import vip.liux.backend.infrastructure.excel.converters.LocalDateTimeStringConverter;
import vip.liux.backend.infrastructure.excel.handler.BaseAnalysisEventListener;
import vip.liux.backend.infrastructure.excel.handler.ManySheetWriteHandler;
import vip.liux.backend.infrastructure.excel.handler.SingleSheetWriteHandler;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;

/**
 * Excel 相关服务，提供通用的 Excel 解析与导出方法
 */
public class ExcelService {


    public static final SingleSheetWriteHandler singleSheetWriteHandler = new SingleSheetWriteHandler();

    public static final ManySheetWriteHandler manySheetWriteHandler = new ManySheetWriteHandler();

    /**
     * 解析 Excel 文件，返回数据列表
     *
     * @param inputStream Excel 文件输入流
     * @param clazz       数据类型
     * @param ctx         导入上下文配置
     * @param <T>         数据类型
     * @return 解析后的数据列表
     * @throws Exception 解析异常
     */
    public static <T> List<?> resolveExcel(InputStream inputStream, Class<T> clazz, ImportContext ctx) throws Exception {
        Class<? extends BaseAnalysisEventListener<?>> readListenerClass = ctx.getReadListener();
        BaseAnalysisEventListener<?> readListener = ConstructorUtils.invokeConstructor(readListenerClass);
        readListener.setHooks(ctx.getHooks());

        EasyExcelFactory.read(inputStream, clazz, readListener)
                .registerConverter(LocalDateStringConverter.INSTANCE)
                .registerConverter(LocalDateTimeStringConverter.INSTANCE)
                .registerConverter(DateStringConverter.INSTANCE)
                .ignoreEmptyRow(ctx.isIgnoreEmptyRow())
                .sheet()
                .headRowNumber(ctx.getHeadRowNumber())
                .doRead();

        return readListener.getList();
    }

    /**
     * 导出 Excel，返回字节数组
     *
     * @param data 导出数据
     * @param ctx  导出上下文配置
     * @return Excel 文件字节数组
     */
    public static byte[] writeExcel(List<?> data, ExportContext ctx) {
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            singleSheetWriteHandler.export(data, byteArrayOutputStream, ctx);
            return byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }


    /**
     * 导出 Excel，返回字节数组
     *
     * @param data 导出数据
     * @param ctx  导出上下文配置
     * @return Excel 文件字节数组
     */
    public static byte[] writeManyExcel(List<List<?>> data, ExportContext ctx) {
        try (ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream()) {
            manySheetWriteHandler.export(data, byteArrayOutputStream, ctx);
            return byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}